4.12. Сборка приложений на мобильные устройства
Сборка приложений на мобильные устройства
Сборка приложения — это завершающий этап жизненного цикла разработки программного обеспечения, в ходе которого исходные тексты программ, ресурсы и метаданные преобразуются в исполняемый артефакт, пригодный к установке и запуску на целевом устройстве. В мобильной разработке сборка обладает повышенной спецификой: она включает в себя не только компиляцию кода, но и конфигурацию платформенно-зависимых аспектов — манифестов, подписей, прав доступа, архитектурных целей, версионирования и упаковки. Мобильная сборка тесно связана с требованиями операционных систем, экосистем распространения приложений и политиками цифровой безопасности. Это делает её процедурой, требующей строгого соблюдения форматов, последовательности действий и контроля целостности получаемого пакета.
Форматы распространяемых пакетов
Распространение мобильного приложения происходит через пакет — единый цифровой контейнер, содержащий все необходимые компоненты для установки и запуска приложения на устройстве. Формат пакета определяется операционной системой, для которой приложение предназначено.
Для операционной системы Android основным форматом пакета является APK — Android Package. Это архив в формате ZIP, содержащий скомпилированный байт-код (в формате DEX), ресурсы — изображения, макеты интерфейса, строки локализации, а также манифест-файл AndroidManifest.xml, в котором объявлены основные характеристики приложения: имя, версия, разрешения, точки входа, используемые службы и получатели событий. APK поддерживает установку на устройства с архитектурой ARM, ARM64, x86 и x86_64, при этом в одном пакете могут содержаться нативные библиотеки для нескольких архитектур. Современная практика предполагает переход к формату AAB — Android App Bundle, который используется при загрузке в Google Play. AAB не устанавливается напрямую на устройство, но служит исходным форматом для генерации оптимизированных APK, адаптированных под конкретную конфигурацию устройства — архитектуру, плотность экрана, языковую локаль. Это позволяет сократить размер загружаемого приложения без потери функциональности.
Для операционной системы iOS основным форматом является IPA — iOS App Store Package. Как и APK, это архив в формате ZIP, но структура и содержимое специфичны для экосистемы Apple. Внутри IPA находится каталог с расширением .app, представляющий собой bundle — иерархическую структуру каталогов, в которой размещены исполняемый файл (скомпилированная программа на машинном коде для ARM64 или ARM64e), ресурсы, локализации, подписи кода и конфигурационные файлы, включая Info.plist. Этот файл содержит метаданные приложения: идентификатор пакета, версию, минимальную поддерживаемую версию iOS, требования к устройству, разрешения и другие атрибуты, определяющие поведение системы при установке и запуске. IPA всегда содержит подпись кода, соответствующую сертификату разработчика, выданному Apple, без которой установка на устройство невозможна — даже в режиме отладки.
Среды разработки и инструментарии сборки
Создание мобильного приложения и его сборка требуют специализированной среды разработки, сочетающей в себе редактор кода, отладчик, инструменты компиляции, конфигуратор сборки и средства развёртывания. Такие среды обычно предоставляются производителями платформ.
Android Studio — официальная интегрированная среда разработки для Android, основанная на IntelliJ IDEA. Внутри неё интегрированы компиляторы, упаковщики, эмулятор устройства, инструменты профилирования и анализа. Сборка в Android Studio управляется системой сборки Gradle, которая интерпретирует декларативные конфигурационные файлы build.gradle. В этих файлах определяются зависимости проекта, версии SDK, варианты сборки (например, debug и release), настройки подписи, правила обфускации и минификации кода. Gradle строит граф зависимостей между модулями, выполняет предварительную обработку ресурсов, компилирует Java- или Kotlin-код в байт-код, преобразует его в DEX-формат, объединяет с нативными библиотеками и упаковывает результат в APK или AAB. Процесс полностью автоматизирован, но допускает детальную настройку на каждом этапе.
Xcode — официальная среда разработки для macOS, iOS, iPadOS, watchOS и tvOS. Xcode включает компилятор Clang, систему сборки Xcode Build System (основанную на xcodebuild), редактор интерфейсов Interface Builder, симулятор iOS, инструменты анализа производительности и архивации. Сборка проекта в Xcode управляется через файл проекта .xcodeproj и схемы сборки — Scheme. В схеме указывается целевая платформа, конфигурация (например, Debug или Release), параметры подписи кода, условия архивации и экспорта. При сборке Xcode компилирует исходный код на Swift или Objective-C в машинный код, объединяет его с ресурсами, встраивает информацию о подписи, генерирует файл entitlements (расширения прав), и формирует исполняемый bundle. Для распространения используется команда Archive, создающая архив .xcarchive, из которого далее экспортируется IPA с нужными настройками подписи и распределения — внутреннего тестирования, App Store или корпоративного развёртывания.
Языки программирования и их роль в сборке
Выбор языка программирования влияет на структуру проекта, используемые инструменты и этапы трансляции.
Для Android традиционно применяются Java и Kotlin. Java компилируется в байт-код JVM с помощью javac, затем преобразуется в DEX-формат утилитой d8 (ранее — dx). Kotlin транслируется в тот же DEX-формат напрямую, через Kotlin-компилятор, совместимый с Java-библиотеками и Android SDK. Оба языка используют общий фреймворк Android API, и сборка их кода интегрирована в Gradle-процесс без принципиальных различий на уровне упаковки.
Для iOS основными языками являются Swift и Objective-C. Swift компилируется в машинный код при помощи фронтенда компилятора LLVM, с применением оптимизаций на уровне модуля и функций. Objective-C компилируется тем же Clang, но сохраняет совместимость с динамической диспетчеризацией через runtime Objective-C. Оба языка поддерживают смешанное использование в одном проекте благодаря механизму мостирования, а сборка объединяет объектные файлы в единый исполняемый образ.
В кроссплатформенной разработке востребованы языки, не зависящие напрямую от нативных стеков. JavaScript — основной язык для фреймворков на базе WebView (Cordova, Capacitor) и React Native — передаётся в бандл как текст или минифицированный артефакт, а выполнение происходит либо в JavaScriptCore (на iOS), либо в V8/QuickJS (на Android). Dart — язык фреймворка Flutter — компилируется в Ahead-of-Time (AOT) машинный код для ARM и ARM64 при сборке в режиме release, обеспечивая высокую производительность, а при отладке используется Just-in-Time (JIT) компиляция через Dart VM, встроенную в движок Flutter. Это позволяет достигать нативного уровня скорости без полного отказа от удобства разработки.
Кроссплатформенные подходы и их сборочные цепочки
Кроссплатформенная разработка подразумевает написание единого кода, который затем транслируется или адаптируется для нескольких целевых платформ. Каждый подход задаёт собственную архитектуру сборки.
React Native использует JavaScript, JSX и нативные модули. Сборка начинается с транспиляции JavaScript-кода с помощью Metro Bundler, который формирует единый пакет index.android.bundle или main.jsbundle. Этот пакет встраивается в нативный проект — Android-приложение на Java/Kotlin или iOS-приложение на Objective-C/Swift. Далее проект собирается обычным способом: через Gradle для Android и Xcode для iOS. Таким образом, итоговый APK или IPA содержит как нативный обёрточный код, так и JavaScript-логику, запускаемую встроенным движком.
Flutter строится на движке, написанном на C++ и Dart. При сборке в режиме отладки Dart-код передаётся в Dart VM по сети, обеспечивая горячую перезагрузку. При сборке в режиме release Dart компилируется в AOT-код, который линкуется со статической библиотекой движка Flutter и встраивается в нативный хост-проект. Для Android это — минимальное приложение на Kotlin, для iOS — на Swift/Objective-C. Результат — единый бинарный образ, не зависящий от внешних интерпретаторов. Сборка управляется командой flutter build, которая вызывает Gradle или xcodebuild в зависимости от целевой платформы.
Xamarin, а в его преемнике — .NET MAUI, использует язык C# и платформу .NET. Сборка выполняется через компилятор Roslyn и инструментарий .NET SDK. C#-код компилируется в промежуточный язык CIL, который затем преобразуется в нативный машинный код с помощью Ahead-of-Time компилятора — mkbundle для Android и mtouch для iOS. Для Android результатом является APK, включающий скомпилированный код Mono Runtime и прикладную логику. Для iOS — IPA, где весь C#-код сведён к машинному представлению и объединён с обёрткой на Objective-C. Это позволяет избежать ограничений Apple на интерпретируемый код, сохраняя при этом общую кодовую базу.
Apache Cordova и Capacitor реализуют подход WebView-обёртки. Исходное приложение — это веб-страница, написанная на HTML, CSS и JavaScript. При сборке создаётся нативный проект с минимальным «хостом» — приложением, содержащим WebView, который загружает локальный стартовый HTML-файл. Ресурсы веб-приложения копируются в каталог ресурсов нативного проекта. Все вызовы к нативным API (камера, геолокация, уведомления) выполняются через плагины — JavaScript-обёртки, транслирующие вызовы в нативные модули. Сборка такого приложения состоит из двух этапов: подготовки веб-ресурсов (часто с помощью инструментов вроде Webpack или Vite) и последующей сборки нативного хоста через Gradle или Xcode. Результат — APK или IPA, визуально идентичный веб-приложению, но имеющий доступ к устройству через мост.
Настройка среды разработки
Настройка среды разработки — это конфигурация программного окружения, необходимого для корректной сборки мобильного приложения. Она включает установку базовых компонентов операционной системы, инструментов компиляции, пакетов SDK, утилит командной строки и цифровых сертификатов.
Для разработки под Android требуется установленная Java Development Kit (JDK) — предпочтительно OpenJDK 17 или выше, совместимая с Android Gradle Plugin. Далее устанавливается Android Studio, которая автоматически загружает Android SDK, включающий:
— Platform Tools (ADB, Fastboot),
— Build Tools (aapt, apksigner, zipalign, d8),
— Platform SDKs (наборы API для целевых версий Android),
— System Images для эмуляторов.
Конфигурация Gradle включает указание compileSdkVersion, targetSdkVersion и minSdkVersion — эти параметры определяют, с каким уровнем API компилируется приложение, на какую версию оно ориентировано и какая минимальная версия поддерживается. Утилита sdkmanager позволяет управлять версиями SDK в автоматизированном режиме. Для сборки из командной строки достаточно установить Android Command Line Tools, без графической оболочки IDE.
Для разработки под iOS требуется компьютер на базе архитектуры Apple Silicon или Intel, с операционной системой macOS. Устанавливается Xcode из App Store — вместе с ним поставляются:
— Xcode Command Line Tools (xcode-select --install),
— Swift и Clang компиляторы,
— Simulator Runtime для различных версий iOS,
— codesign, security, altool и другие утилиты цифровой подписи и архивации.
Xcode управляет версиями SDK через встроенный менеджер компонентов. Каждая версия Xcode поддерживает фиксированный диапазон целевых версий iOS — например, Xcode 15.x поддерживает сборку для iOS 17 и выше. Обновление Xcode может быть необходимо при появлении новых функций API или изменений в требованиях к подписи.
Для кроссплатформенных фреймворков настройка дополняется установкой соответствующих SDK:
— Flutter SDK включает движок, Dart SDK и CLI-инструмент flutter;
— React Native требует Node.js, npm/yarn, Metro Bundler и CocoaPods (для iOS-зависимостей);
— .NET MAUI требует .NET 8 SDK и Visual Studio 2022 (на Windows) или Visual Studio for Mac.
Важной частью настройки является конфигурация переменных окружения (PATH, ANDROID_HOME, JAVA_HOME) и проверка доступности инструментов через командную строку. Автоматизированные скрипты инициализации среды позволяют обеспечить воспроизводимость сборки в CI/CD-конвейерах.
Выполнение сборки в интегрированной среде
Сборка в IDE происходит по заранее определённой схеме, состоящей из логически последовательных этапов. Эти этапы реализованы в виде задач или фаз, управляемых системой сборки.
В Gradle для Android процесс включает следующие ключевые фазы:
— preBuild — подготовка, включая анализ зависимостей и валидацию конфигурации;
— generateDebug/ReleaseResources — обработка XML-ресурсов, генерация R.java, объединение строк локализации, компиляция макетов в двоичный формат;
— compileDebug/ReleaseKotlin/JavaWithJavac — компиляция исходного кода в .class-файлы, затем в DEX-байт-код с помощью d8;
— mergeDebug/ReleaseJniLibFolders — объединение нативных .so-библиотек из зависимостей и модулей;
— processDebug/ReleaseManifest — слияние манифестов модулей, подстановка значений из build.gradle, валидация разрешений;
— mergeDebug/ReleaseAssets — копирование статических ресурсов (шрифты, JSON, медиа);
— packageDebug/Release — упаковка APK: формирование ZIP-архива, выравнивание с помощью zipalign, подпись с помощью apksigner (в режиме debug — автоматической отладочной подписью);
— bundleRelease — для AAB: формирование App Bundle с метаданными о конфигурациях устройств.
В Xcode сборка управляется Build System и включает:
— Parsing — чтение .xcodeproj, схем и целей;
— Dependency Analysis — построение графа зависимостей модулей, файлов и ресурсов;
— Compilation — компиляция .swift и .m/.h файлов в объектные файлы .o;
— Linking — объединение объектных файлов, библиотек и фреймворков в единый исполняемый образ;
— Copying Resources — копирование изображений, локализаций, storyboards в bundle;
— Code Signing — встраивание подписи и entitlements в исполняемый файл и bundle;
— Packaging — формирование .app, затем — при экспорте — .ipa.
В Flutter команда flutter build запускает:
— анализ зависимостей через pub;
— компиляцию Dart-кода в AOT-бинарь (для --release) или подготовку JIT-сервера (для --debug);
— генерацию нативного хост-проекта (если требуется);
— вызов Gradle для Android или xcodebuild для iOS с передачей скомпилированного ядра.
Для React Native сборка разделяется: сначала bundle-файл генерируется Metro, затем нативная часть собирается в Android Studio или Xcode. При обновлении JavaScript-логики в режиме отладки повторная сборка нативной части не требуется.
Тестирование на эмуляторах и физических устройствах
Тестирование — обязательный этап перед финальной сборкой. Оно позволяет проверить корректность поведения приложения в условиях, приближенных к реальным.
Эмуляторы Android основаны на виртуальной машине QEMU и позволяют имитировать различные конфигурации устройств: версии Android, разрешения экрана, плотность пикселей, объём оперативной памяти, наличие сенсоров. Эмулятор поддерживает ADB-соединение, отладку через Android Studio, ввод через клавиатуру и имитацию геопозиции, звонков, SMS. Для ускорения используется технология аппаратного ускорения — Intel HAXM или Apple Hypervisor Framework. Эмуляторы полезны для раннего обнаружения ошибок совместимости.
Симуляторы iOS — это не эмуляторы в строгом смысле, а нативные приложения, запускающие iOS-код на macOS. Они используют ту же архитектуру x86_64 или arm64, что и хост-система, поэтому сборка для симулятора отличается от сборки для устройства — используется другой SDK (iphonesimulator вместо iphoneos) и другие библиотеки. Симулятор точно воспроизводит интерфейс, анимации, работу с локализацией, но не поддерживает все нативные API — например, ARKit или некоторые функции Bluetooth. Он не требует подписи кода в режиме отладки.
Тестирование на физических устройствах даёт наиболее достоверные результаты. Устройство подключается по USB, разрешает отладку (Android) или добавляется в provisioning profile (iOS). На Android активируется «Режим разработчика» и «Отладка по USB», после чего ADB устанавливает отладочную сборку с автоматической подписью. На iOS устройство регистрируется в Apple Developer Account, в Xcode выбирается команда разработки, и Xcode автоматически генерирует development provisioning profile, связывающий устройство, приложение и сертификат. Установка происходит мгновенно, с возможностью live-отладки, профилирования памяти и энергопотребления.
Для автоматизированного тестирования применяются инструменты:
— Espresso и UI Automator для Android,
— XCTest и XCUITest для iOS,
— Detox или Appium для кроссплатформенных решений.
Тестовые сборки могут включать дополнительные логи, телеметрию и диагностические интерфейсы, недоступные в релизной версии.
Цифровая подпись сборки
Цифровая подпись — механизм обеспечения подлинности, целостности и доверия к приложению. Она подтверждает, что пакет создан авторизованным разработчиком и не был изменён после подписания.
На Android подпись реализуется с помощью ключевого хранилища — файла формата JKS (Java KeyStore) или PKCS12. В нём содержится закрытый ключ и сертификат разработчика. Подпись выполняется утилитой apksigner, которая добавляет в APK блок META-INF/MANIFEST.MF, CERT.SF и CERT.RSA (или .EC). Для отладки Android Studio использует автоматически сгенерированное хранилище debug.keystore. Для релиза требуется release keystore — файл, созданный вручную и строго охраняемый. Google рекомендует использовать Play App Signing, при котором Google хранит upload key, а Google Play использует отдельный app signing key для финальной подписи перед распространением. Это позволяет восстановить доступ к обновлениям при утере ключа.
На iOS подпись строится на инфраструктуре сертификатов Apple. Разработчик генерирует Certificate Signing Request (CSR) в Keychain Access, загружает его в Apple Developer Portal, получает Development или Distribution Certificate (в формате .cer), который устанавливается в системный Keychain. Далее создаётся App ID — уникальный идентификатор пакета (Bundle ID), и Provisioning Profile — файл, связывающий сертификат, App ID и список зарегистрированных устройств (для development) или разрешающий распространение через App Store/Enterprise (для distribution). Xcode автоматически выбирает подходящий профиль и выполняет подпись с помощью codesign. Проверка подписи происходит на устройстве при каждой установке и запуске.
Подпись необратимо связана с идентификатором приложения. Обновление приложения возможно только при использовании того же ключа (Android) или того же App ID и сертификата (iOS). Смена подписи требует полного удаления предыдущей версии.
Создание пакета для распространения
Финальный этап — подготовка артефакта, пригодного для публикации в магазинах приложений или внутреннего распространения.
Для Google Play основным форматом является AAB. Он генерируется командой ./gradlew bundleRelease. Внутри AAB содержатся:
— базовый модуль приложения,
— динамические модули (feature modules),
— метаданные о конфигурациях устройств (ABI, density, language),
— подпись upload key.
После загрузки в Play Console Google проверяет пакет, сканирует на уязвимости, формирует delivery APKs (base APK + configuration APKs) и подписывает их своим ключом (если включено Play App Signing). Разработчик получает возможность тестирования через Internal Testing, Closed Testing, Open Testing Track.
Для App Store требуется IPA, сгенерированный из .xcarchive. Архив создаётся в Xcode: Product → Archive. После завершения архивации открывается Organizer, где выбирается архив и выполняется Distribute App → App Store Connect. Xcode экспортирует IPA, применяя:
— Bitcode (если включён) — промежуточное представление кода, позволяющее Apple выполнять дополнительную оптимизацию,
— Symbolication — включение символьных таблиц для краш-аналитики (опционально),
— Trimming — удаление ненужных архитектур (например, x86_64 для симулятора).
Экспортированный IPA загружается в App Store Connect через Transporter или Xcode. Там проходит автоматическую проверку (App Store Review Guidelines), после чего становится доступен для TestFlight или публичной публикации.
Для альтернативных каналов — корпоративного развёртывания, бета-тестирования вне магазинов — используются:
— APK с release-подписью (Android), устанавливаемый вручную или через MDM-системы,
— IPA с Enterprise Distribution Certificate (iOS), распространяемый через внутренний веб-портал с manifest-файлом,
— Firebase App Distribution, Microsoft App Center, TestFlight — платформы, упрощающие доставку тестовых сборок.
Каждая финальная сборка сопровождается версионированием: указанием versionCode/versionName (Android) или CFBundleVersion/CFBundleShortVersionString (iOS). Эти значения участвуют в механизмах обновления и аналитики.
Архитектурные целевые платформы и управление размером приложения
Современные мобильные устройства используют процессоры с архитектурой ARM. Сборка приложения должна учитывать набор инструкций, на котором будет выполняться нативный код. Для Android это проявляется в поддержке Application Binary Interfaces (ABI):
— armeabi-v7a — 32-битный ARM, устаревший, но сохраняется для совместимости с устройствами до 2016 года;
— arm64-v8a — 64-битный ARM, основной формат для всех современных устройств;
— x86 и x86_64 — эмуляторы и редкие устройства на Intel, в основном для отладки.
Gradle позволяет указать, для каких ABI генерировать нативные библиотеки, через параметр ndk.abiFilters. Исключение ненужных архитектур сокращает размер APK. При использовании AAB Google Play автоматически раздаёт только нужные нативные библиотеки, исключая избыточность без участия разработчика.
Для iOS поддержка 32-битного кода прекращена с iOS 11. Все приложения компилируются строго под arm64 (или arm64e — с расширениями безопасности на новых чипах Apple). При сборке Xcode автоматически отбрасывает лишние срезы (slices) из универсальных бинарных файлов (fat binaries), оставляя только целевую архитектуру. Это делает IPA компактнее без дополнительной настройки.
Управление размером приложения — важная инженерная задача. Крупные пакеты снижают конверсию установок, особенно в регионах с дорогим или медленным интернетом. Стратегии сокращения включают:
— Сжатие ресурсов: использование WebP вместо PNG, удаление EXIF-данных из изображений, квантования цветов;
— Удаление неиспользуемых ресурсов: анализ через Android Lint или resourceConfigs в Gradle, проверка локализаций на наличие пустых строк;
— Разделение функционала на модули: Dynamic Feature Modules (Android) и On-Demand Resources (iOS) позволяют загружать части приложения по требованию — например, уровень игры или модуль отчётов;
— Использование векторной графики: SVG в Android (через VectorDrawable) и PDF в iOS (через Assets Catalog) заменяют набор растровых изображений под разные DPI;
— Оптимизация зависимостей: исключение транзитивных библиотек с помощью api/implementation, анализ дерева зависимостей (./gradlew dependencies), замена тяжёлых SDK на лёгкие аналоги.
Google Play накладывает ограничение на размер AAB — 150 МБ для базового модуля, до 2 ГБ с учётом динамических модулей и внешних ресурсов. App Store требует, чтобы размер загружаемого IPA не превышал 4 ГБ, но рекомендует укладываться в 100 МБ для мгновенной загрузки по мобильному интернету.
Минификация и обфускация кода
Минификация — процесс сокращения объёма исходного кода без изменения его семантики. Обфускация — преобразование кода с целью затруднения его анализа и обратной разработки. Обе процедуры применяются в релизных сборках и интегрированы в стандартные инструменты.
В Android минификация и обфускация выполняются системой R8 (преемник ProGuard). R8:
— удаляет неиспользуемые классы, методы, поля (tree shaking);
— переименовывает оставшиеся сущности в короткие имена (a, b, c);
— сливает классы и методы, где это возможно;
— инлайнит простые вызовы;
— генерирует mapping-файл для восстановления стек-трейсов при крашах.
Активация происходит в build.gradle параметром minifyEnabled true и shrinkResources true. Правила сохранения критически важных элементов (например, классов, вызываемых через reflection) задаются в файлах proguard-rules.pro. Без корректных правил приложение может потерять функциональность при сборке релиза.
В iOS обфускация не встроена в Xcode, но реализуется сторонними инструментами:
— переменные и функции переименовываются в случайные строки;
— строки кода шифруются и расшифровываются во время выполнения;
— вставляются ложные ветвления и мёртвый код.
Apple не запрещает обфускацию, но требует, чтобы исполняемый код оставался валидным и проходил проверку через otool и codesign --verify. Использование Swift снижает потребность в обфускации, так как его бинарный формат сложнее для декомпиляции, чем Objective-C.
В кроссплатформенных решениях:
— Flutter при сборке в --release включает AOT-компиляцию и tree shaking на уровне Dart-кода, что делает бинарь компактным и устойчивым к анализу;
— React Native позволяет минифицировать JavaScript-бандл с помощью Metro (--minify), но код остаётся текстовым — полная защита требует дополнительных мер вроде шифрования бандла и кастомного загрузчика;
— .NET MAUI использует IL Linker для удаления неиспользуемого кода и TrimMode для контроля глубины усечения.
Обфускация не гарантирует абсолютную защиту, но повышает порог входа для нецелевых атак. Для критически важных алгоритмов рекомендуется вынос логики на сервер.
Локализация и региональная адаптация сборки
Локализация — не просто перевод строк, а комплексная адаптация приложения под языковые, культурные и правовые особенности целевых рынков. Сборка должна поддерживать генерацию вариантов, учитывающих эти различия.
В Android локализация управляется через каталоги ресурсов:
— values/strings.xml — базовые строки,
— values-ru/strings.xml — строки для русского языка,
— values-ru-rRU/strings.xml — строки для русского языка в России,
— values-land/, values-sw600dp/ — адаптация под ориентацию и размер экрана.
Gradle позволяет собирать языковые APK — отдельные пакеты, содержащие только одну локаль. При использовании AAB Google Play автоматически формирует мультиязычные конфигурации и отдаёт пользователю только нужную локаль. Для стран с особыми требованиями (например, Китай) возможна сборка отдельного варианта с заменой аналитических SDK и серверных эндпоинтов.
В iOS локализация реализуется через Base Internationalization и .strings-файлы в каталогах ru.lproj/, zh-Hans.lproj/ и т.д. Xcode поддерживает экспорт локализаций в формат XLIFF для передачи переводчикам. Provisioning Profile и сертификаты не зависят от локали, поэтому один IPA может содержать все языки. Для App Store требуется указание поддерживаемых языков в метаданных приложения.
Региональная адаптация включает:
— изменение формата дат, времени, чисел, валют;
— замену изображений с учётом культурных норм;
— модификацию логики — например, отключение функций, запрещённых в отдельных юрисдикциях;
— включение местных платёжных систем (Мир, WeChat Pay).
Сборка для разных регионов может выполняться через flavors (Android) или targets/schemes (iOS) — отдельные конфигурации, наследующие общую кодовую базу, но имеющие свои ресурсы, константы и зависимости.
Интеграция сборки в CI/CD-конвейеры
Автоматизация сборки повышает воспроизводимость, ускоряет доставку и снижает человеческий фактор. CI/CD-конвейер включает этапы: сборка, тестирование, артефактное хранение, доставка.
Типичная конфигурация на GitHub Actions для Android:
— восстановление кэша Gradle и зависимостей;
— сборка bundleRelease с передачей подписи через зашифрованные секреты (RELEASE_STORE_FILE, RELEASE_KEY_ALIAS);
— запуск unit- и instrumented-тестов;
— загрузка AAB в Firebase App Distribution или Google Play через google-play-deploy action.
Для iOS:
— установка Xcode через setup-xcode;
— импорт сертификата и provisioning profile из секретов (p12-файл и .mobileprovision);
— сборка xcodebuild archive -exportArchive;
— загрузка IPA в TestFlight через Transporter или altool.
Специализированные платформы:
— Bitrise предлагает визуальный конструктор workflow с преднастроенными шагами для подписи, сборки и деплоя;
— Fastlane — DSL на Ruby для автоматизации рутинных операций: match для управления сертификатами, gym для сборки, pilot для загрузки в TestFlight, supply для метаданных Play Console;
— Codemagic оптимизирован под Flutter и React Native, поддерживает сборку под обе платформы из одного репозитория.
Все конвейеры требуют строгого контроля секретов — ключей подписи, сертификатов, API-токенов. Используются зашифрованные переменные окружения, Hardware Security Modules (HSM) в enterprise-средах, и временные сертификаты для CI-only сборок.
Типичные ошибки сборки и диагностика
Сбои в сборке могут возникать на любом этапе. Диагностика основывается на анализе логов, проверке конфигурации и системных требований.
Частые причины ошибок в Android:
— несовместимость версий Gradle, AGP и JDK;
— отсутствие требуемой версии Build Tools (failed to find target with hash string);
— конфликт зависимостей (дублирующие классы из разных библиотек);
— утечка памяти в процессе сборки (требуется увеличение org.gradle.jvmargs);
— неверный путь к keystorе или неправильный пароль (keystore password was incorrect).
В iOS:
— устаревший provisioning profile (profile doesn't match bundle identifier);
— отсутствие сертификата в Keychain (no signing certificate found);
— несовпадение capabilities в Xcode и в App ID на портале (например, Push Notifications не включены);
— ошибка bitcode (bitcode bundle could not be generated при несовместимости библиотек);
— истёкший срок действия сертификата разработчика.
Инструменты диагностики:
— ./gradlew build --stacktrace --info — детальные логи Android-сборки;
— xcodebuild -showBuildSettings — проверка текущей конфигурации;
— codesign -dv --verbose=4 Payload/*.app — проверка подписи IPA;
— aapt2 dump badging app.apk — анализ содержимого APK;
— plutil -lint Info.plist — валидация plist-файлов.
Систематическая организация логов, использование уникальных версий сборки (versionCode, buildNumber) и артефактное хранение всех промежуточных файлов позволяют точно локализовать источник проблемы.
Внешние требования
Финальная сборка должна соответствовать не только техническим, но и внешним требованиям — со стороны магазинов приложений, регуляторов и платформ.
Google Play Console требует:
— указания целевой targetSdkVersion не ниже актуальной (каждый год обновляется);
— декларации всех используемых разрешений с обоснованием (<uses-permission> + android:usesPermissionFlags);
— наличия политики конфиденциальности, доступной по ссылке в описании;
— соответствия политике семьи (если приложение для детей);
— прохождения проверки SafetyNet/Play Integrity для приложений с высоким уровнем привилегий.
App Store Connect проверяет:
— соответствие Guidelines (раздел 4 — Design, 5 — Legal);
— корректность возраста рейтинга (based on content descriptors);
— наличие NSPrivacyManifest.plist для SDK, начиная с iOS 17.2 — обязательное описание использования данных;
— поддержку Dark Mode и Dynamic Type;
— отсутствие скрытых функций или «закладок».
Региональные ограничения влияют на состав сборки:
— в России требуется маркировка «Реклама» при наличии рекламы, соблюдение 152-ФЗ о персональных данных, хранение данных граждан на территории РФ;
— в ЕС — соответствие GDPR, в том числе механизм согласия на трекинг (App Tracking Transparency для iOS);
— в Китае — интеграция с локальными сервисами (WeChat SDK), прохождение лицензирования MIIT.
Несоответствие этим требованиям приводит к отклонению приложения при модерации или последующему удалению из магазина. Проверка проводится как автоматическими сканерами, так и ручным ревью.
Сборка для специализированных платформ
Мобильная экосистема выходит за рамки смартфонов. Сборка приложений для носимых устройств, телевизоров и автомобильных систем требует учёта ограничений аппаратной платформы, особенностей пользовательского взаимодействия и специфических требований к производительности.
Wear OS (Android для умных часов) использует тот же инструментарий, что и Android, но с дополнительными ограничениями. Приложение должно быть совместимо с круглыми и прямоугольными экранами, поддерживать жесты вместо точного тача, минимизировать энергопотребление. Сборка может происходить двумя способами:
— как отдельное приложение на часах, с собственным wear-модулем в проекте, использующим minSdkVersion 28 и специфичные библиотеки (WearOSSupport, Tiles, Complications);
— как часть companion-приложения на смартфоне, где часы получают уведомления и простые действия через NotificationCompat.Builder.
Формат пакета — APK или AAB, но с фильтрацией по android.hardware.type.watch в манифесте. Google Play требует отдельного скриншота интерфейса часов и тестирования на эмуляторе Wear OS.
watchOS строится на основе iOS, но с собственной средой выполнения. Приложение состоит из двух частей:
— WatchKit Extension — логика, исполняемая на Apple Watch;
— Watch App — интерфейс, упакованный в отдельный bundle.
Сборка выполняется в Xcode: выбирается схема YourApp WatchKit App, задаётся target watchos, и запускается Archive. Результат — один IPA, содержащий как iOS-часть, так и watchOS-часть, с отдельными исполняемыми файлами и ресурсами. watchOS не поддерживает фоновую активность длительного времени, поэтому логика сборки включает строгую проверку жизненного цикла компонентов.
Android TV и Fire TV требуют адаптации под 10-футовый интерфейс — управление с пульта, крупные элементы, отсутствие сенсорного ввода. В манифесте объявляется CATEGORY_LEANBACK_LAUNCHER, используется библиотека Leanback, отключаются функции, не имеющие смысла на ТВ (камера, геолокация в реальном времени). Сборка — стандартный APK/AAB, но с указанием android:required="false" для feature-элементов, отсутствующих на ТВ (например, android.hardware.touchscreen). Google Play проверяет наличие TV-скриншотов и совместимость с Leanback UI.
Автомобильные платформы:
— Android Automotive OS — полноценная операционная система, встроенная в автомобиль. Приложение устанавливается напрямую на IVI-систему, как на обычный Android-девайс, но с ограничениями: запрет на всплывающие окна, требуется поддержка CarAppService, строгая проверка энергопотребления. Сборка — через Android Studio, с эмулятором Automotive.
— Android Auto и Apple CarPlay — проекция с телефона. Приложение выполняется на смартфоне, а интерфейс отображается на экране автомобиля через защищённый протокол. Для Android используется библиотека Car App Library, для iOS — CarPlay framework. Сборка не отличается от обычной, но при публикации требуется дополнительное тестирование на совместимость с головными устройствами и одобрение от Google/Apple.
Во всех случаях сборка включает отдельные ресурсы (макеты, изображения, строки), конфигурации Gradle/Xcode, и процедуры тестирования на специализированных симуляторах.
Новые форматы доставки: Dynamic Delivery и App Clips
Эволюция магазинов приложений направлена на снижение барьера входа для пользователей. Новые форматы позволяют доставлять функциональность без полной установки.
Android App Bundle и Dynamic Delivery предоставляют гибкость распределения:
— Base APK содержит минимально необходимый код и ресурсы для запуска;
— Configuration APKs — ресурсы, специфичные для устройства (язык, DPI, ABI);
— Dynamic Feature Modules — опциональные функции, загружаемые по требованию (SplitInstallManager);
— Asset Packs — крупные данные (текстуры, аудио), загружаемые с приоритетом (install-time, fast-follow, on-demand).
Сборка AAB включает декларацию dist:title, dist:onDemand, dist:delivery в module.xml. Google Play Console визуализирует размеры модулей и позволяет тестировать разные сценарии загрузки. Это позволяет приложению стартовать за секунды, а остальное докачивать в фоне.
iOS App Clips — мини-версии приложений (до 10 МБ), запускаемые по NFC, QR-коду или ссылке без установки полноценного приложения. App Clip — отдельная цель в Xcode (App Clip target), наследующая кодовую базу основного приложения, но с ограничениями:
— отсутствие background modes, push-уведомлений, Siri intents;
— доступ только к части API (например, Core NFC, Camera для QR);
— автоматическая ассоциация с полным приложением по Bundle ID с суффиксом .clip.
Сборка выполняется через xcodebuild archive, с указанием схемы App Clip. Результат — отдельный IPA, загружаемый в App Store Connect в разделе App Clips. После первого использования система предлагает установить полное приложение — без дублирования данных.
Эти форматы требуют пересмотра архитектуры: выделения ядра, планирования точек расширения, проектирования «бесшовного» перехода от лёгкой к полной версии.
Энергоэффективность и влияние сборки на ресурсы устройства
Сборка оказывает прямое влияние на энергопотребление, нагрев и время автономной работы. Оптимизация на этапе сборки — более эффективный подход, чем постфактумный рефакторинг.
В Android:
— JobScheduler и WorkManager заменяют AlarmManager и фоновые сервисы, группируя задачи для минимизации пробуждений CPU;
— Doze Mode и App Standby требуют корректного объявления WAKE_LOCK и использования setAndAllowWhileIdle;
— нативные библиотеки должны компилироваться с -O2 или -Oz, а не -O0;
— исключение android:debuggable="true" в релизе предотвращает избыточную нагрузку от отладочных хуков.
В iOS:
— Background App Refresh должен быть включён осознанно, с минимальной частотой;
— Location Services используют significant location changes вместо постоянного GPS;
— Energy Log в Instruments позволяет выявить «жадные» потоки и блокировки;
— отключение DEBUG-флагов и NSAssert в релизной сборке снижает накладные расходы.
Компиляторы вносят вклад:
— LTO (Link-Time Optimization) в Clang объединяет оптимизацию на уровне модулей;
— Whole Program Optimization в Gradle повышает эффективность DEX-кода;
— Dart AOT генерирует компактный машинный код без overhead JIT.
Инструменты профилирования — Android Battery Historian, Xcode Energy Debugger — применяются на этапе тестирования сборки, а не только при разработке.
Управление версиями, откат и A/B-тестирование сборок
Версионирование — не только нумерация, а стратегия управления жизненным циклом приложения. Современные подходы включают фрагментацию и контролируемое развёртывание.
Версионные схемы:
— versionCode (Android) и CFBundleVersion (iOS) — строго возрастающие целые числа, управляющие обновлениями в системе;
— versionName/CFBundleShortVersionString — человекочитаемая строка (например, 2.4.1), отображаемая в магазине.
Соглашения вроде Semantic Versioning (MAJOR.MINOR.PATCH) помогают командам согласовывать изменения API.
Откат сборки возможен через:
— выпуск новой сборки с увеличенным versionCode, но старой функциональностью;
— использование feature flags, позволяющих деактивировать проблемный код без пересборки;
— встроенные механизмы магазинов: Google Play позволяет откатить на предыдущую версию в течение 14 дней, App Store — через выпуск новой версии.
A/B-тестирование сборок реализуется:
— через Firebase Remote Config — динамическое переключение функций без обновления;
— через Google Play Internal Testing Track — раздача разных AAB разным группам тестировщиков;
— через TestFlight Groups — разделение бета-пользователей на сегменты с разными IPA.
Сборка для A/B-теста может включать инструментацию: уникальные идентификаторы сборки, расширенную телеметрию, пометки эксперимента в логах.
Это позволяет проверять гипотезы о производительности, вовлечённости и стабильности до полного релиза.
Архивация и долгосрочное хранение артефактов
Каждая сборка — юридически значимый артефакт. Её сохранение необходимо для аудита, отладки критических инцидентов и восстановления сервисов.
Практики архивации включают:
— хранение всех релизных AAB/IPA в системе артефактов (Nexus, Artifactory, JFrog);
— сохранение mapping-файлов обфускации в привязке к versionCode;
— сохранение точной конфигурации сборки: версии JDK, Gradle, Xcode, хеш коммита в Git;
— использование immutable tags в репозитории (например, release/v2.4.1).
Для enterprise-приложений требуется хранение в течение срока действия лицензии + 5 лет — в соответствии с требованиями регуляторов. Инструменты вроде Build Info в JFrog позволяют связать артефакт с полным билд-билетом — окружением, зависимостями, логами.
Воспроизводимая сборка (reproducible build) — высшая ступень зрелости: при одинаковом исходном коде и конфигурации любой участник может получить бинарный идентичный артефакт. Android поддерживает это через --no-aapt2-daemon, --stable-ids, фиксированное зеркало зависимостей. Это критично для open-source проектов и систем с повышенными требованиями к безопасности.
Этические и профессиональные принципы сборки
Процесс сборки несёт ответственность перед пользователями, разработчиками и обществом. Современные практики включают:
Прозрачность:
— публикация конфигурации сборки (например, build.gradle, Podfile.lock) в open-source проектах;
— указание точных версий зависимостей, избегание + в номерах версий;
— документирование шагов сборки в BUILDING.md.
Безопасность цепочки поставок:
— проверка целостности зависимостей через checksum-файлы;
— использование signed artifacts для SDK;
— scanning на уязвимости (OWASP Dependency-Check, Snyk) на этапе CI.
Уважение к пользователю:
— отказ от встраивания скрытых аналитических SDK без согласия;
— минимизация размера сборки как проявление заботы о трафике и хранилище пользователя;
— поддержка старых устройств через отдельные сборки, где это технически возможно.
Экологическая ответственность:
— оптимизация энергопотребления снижает углеродный след миллиардов устройств;
— сокращение размера приложения уменьшает объём передаваемых данных и нагрузку на дата-центры.
Сборка — не техническая рутина, а акт проектирования доверия. Каждый APK и IPA — это договор между разработчиком и пользователем, закодированный в битах.